﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

/// <summary>
/// 技能状态系统(驱动技能状态更改)
/// </summary>
public class SkillStatusSystem : ECSSystemtBase
{
    //后期加入字符来判断此次是否已进入前中后摇来减少额外状态更改

    public override Type[] GetFilter()
    {
        return new Type[]
        {
            typeof(SkillStatusComponent),
        };
    }

    private List<ECSEntityBase> list;
    private int m_listCount;
    public override void FixedUpdate(int delaTime)
    {
        list = GetEntityList();
        m_listCount = list.Count;
        if (m_listCount.Equals(0))
        {
            return;
        }

        for (int i = 0; i < m_listCount; i++)
        {
            SkillStatusLogic(list[i], delaTime);//遍历实体的技能状态
        }
    }

    private SkillStatusComponent sc;
    /// <summary>
    /// 技能开始了多久
    /// </summary>
    private int skillTime;
    /// <summary>
    /// 技能是否只有一段
    /// </summary>
    private bool isOnlySkill;
    /// <summary>
    /// 获取当前技能一段持续时间
    /// </summary>
    private float MaxBeforeTime;
    void SkillStatusLogic(ECSEntityBase entity, int deltaTime)
    {
        sc = entity.GetCom<SkillStatusComponent>();
        //如果技能无状态，或结束状态
        if (sc.m_skillStatus == SkillStatusEnum.None || sc.m_skillStatus == SkillStatusEnum.Finish)
        {
            return;
        }
        //存在技能并且正在进行

        sc.m_skillTime += deltaTime;//当前技能时间自增
        sc.FXTimer += deltaTime;//当前技能特效时间自增
        skillTime = sc.m_skillTime;//更新当前技能时间临时变量

        //获取当前技能一段持续时间
         MaxBeforeTime = sc.m_currentSkillData.ATime;

        #region 伤害判定

        skillHitOneOrTwo(sc.m_skillStatus, deltaTime, sc, entity);

        #endregion

        #region 如果只有一段,不执行第二段操作,短路后续操作

        if (sc.onlyBefore)
        {
            //持续时间大于一段最大时间
            if (skillTime > MaxBeforeTime)
            {
                sc.m_skillStatus = SkillStatusEnum.Finish;//当前技能结束
                sc.m_isEnter = true;//更改了技能当前状态
                sc.m_skillStatus = SkillStatusEnum.Finish;//当前技能结束状态
                //派发技能冷却事件
                MyWorld.eventSystem.DispatchListener(GameUtils.c_SkillStatusEnter, entity);

                return;
            }
            return;
        }


        #endregion

        #region 二段判断
    
        //如果可以进入二段
        if (GoBskillStatu(skillTime,MaxBeforeTime,sc.BMaxWaiteTime,sc.skillCkick,sc.m_skillStatus))
        {

            sc.m_isEnter = true;//更改了技能当前状态

            sc.m_skillStatus = SkillStatusEnum.Current;//尝试更改为二段状态，后期继续修改

            //派发技能二段开始事件
            MyWorld.eventSystem.DispatchListener(GameUtils.c_SkillStatusEnter, entity);


            return;
        }
        
        #endregion

        #region 二段技能等待超时（）
        //如果技能开始时长大于一段+二段时间
        if (skillTime > sc.BMaxWaiteTime)
        {
            sc.m_isHit = false;//不再进行伤害判定

            sc.m_isEnter = true;  //更改了技能当前状态
            sc.m_skillStatus = SkillStatusEnum.Finish;//当前技能结束
            //派发技能结束事件
            MyWorld.eventSystem.DispatchListener(GameUtils.c_SkillStatusEnter, entity);

        }
        #endregion

    }
    /// <summary>
    /// 是否可以进入第二段
    /// </summary>
    /// <param name="skillTime">技能已运行时长</param>
    /// <param name="MaxBeforeTime">一段所用时长</param>
    /// <param name="bWaitMaxTime">二段最大等待时长</param>
    /// <param name="clickNum">点击二段</param>
    /// <param name="thisEnum">释放处于一段</param>
    /// <returns></returns>
    private bool GoBskillStatu(float skillTime, float MaxBeforeTime,float bWaitMaxTime, int clickNum, SkillStatusEnum thisEnum)
    {
        return (skillTime > MaxBeforeTime &&
                skillTime< bWaitMaxTime&&
                clickNum==2&&
                thisEnum==SkillStatusEnum.Before
                );

    }

    /// <summary>
    /// 判断执行一段/二段伤害
    /// </summary>
    /// <param name="thisEnmu"></param>
    private void skillHitOneOrTwo(SkillStatusEnum thisEnmu,int deltaTime,SkillStatusComponent sc,ECSEntityBase entity)
    {
        switch (thisEnmu)
        {
            case SkillStatusEnum.Before:
                BeroreOrCurrentHit(deltaTime, MaxBeforeTime, sc, entity);
                break;
            case SkillStatusEnum.Current:
                BeroreOrCurrentHit(deltaTime, sc.m_currentSkillData.BTime, sc, entity);
                break;
            default:
                throw new Exception("伤害判定出错，非一段/二段伤害枚举");
        }
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="deltaTime"></param>
    /// <param name="continuedTime">技能持续时间</param>
    /// <param name="sc"></param>
    /// <param name="entity"></param>
    private void BeroreOrCurrentHit(int deltaTime,float continuedTime, SkillStatusComponent sc,ECSEntityBase entity)
    {
        if (skillTime < continuedTime)
        {
            //如果是瞬间伤害
            if (sc.m_currentSkillData.SkillInfo.m_Moment)
            {
                //由于瞬间伤害只进行一次计算
                //那么技能此次未触发的话
                if (sc.m_isTriggerSkill == false)//如果技能没有触发
                {
                    sc.m_isTriggerSkill = true;//认定技能已触发过

                    sc.m_isHit = true;//伤害判定开始



                    MyWorld.eventSystem.DispatchListener(GameUtils.c_SkillHit, entity);
                }
                else//如果技能触发过了
                {
                    sc.m_isHit = false;//伤害判定关闭
                }
            }
            //如果是持续伤害
            else
            {
                //非瞬间伤害技能的伤害持续时间剩余-运行时间
                sc.m_skillTrigerTimeSpace -= deltaTime;
                //如果伤害间隔小于0（可能已进行过伤害判定了），取间隔时间
                if (sc.m_skillTrigerTimeSpace < 0)
                {
                    sc.m_skillTrigerTimeSpace = (int)(sc.m_currentSkillData.SkillInfo.m_TriggerSpaceTime) * 1000;

                    sc.m_isHit = true;//开始进行伤害判定



                    MyWorld.eventSystem.DispatchListener(GameUtils.c_SkillHit, entity);
                }
                else
                {
                    sc.m_isHit = false;//未到间隔时间，不进行伤害判定
                }
            }
        }
    }

}

